/**
 * 性能优化工具函数
 */

// 防抖函数
export function debounce(func, wait, immediate = false) {
  let timeout;
  return function executedFunction(...args) {
    const later = () => {
      timeout = null;
      if (!immediate) func(...args);
    };
    const callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) func(...args);
  };
}

// 节流函数
export function throttle(func, limit) {
  let inThrottle;
  return function(...args) {
    if (!inThrottle) {
      func.apply(this, args);
      inThrottle = true;
      setTimeout(() => inThrottle = false, limit);
    }
  };
}

// 缓存函数
export function memoize(fn, keyGenerator = null) {
  const cache = new Map();
  
  return function(...args) {
    const key = keyGenerator ? keyGenerator(...args) : JSON.stringify(args);
    
    if (cache.has(key)) {
      return cache.get(key);
    }
    
    const result = fn.apply(this, args);
    cache.set(key, result);
    
    // 限制缓存大小
    if (cache.size > 100) {
      const firstKey = cache.keys().next().value;
      cache.delete(firstKey);
    }
    
    return result;
  };
}

// 虚拟滚动优化
export function createVirtualScroller(itemHeight, containerHeight) {
  return {
    itemHeight,
    containerHeight,
    visibleCount: Math.ceil(containerHeight / itemHeight) + 2,
    
    getVisibleRange(scrollTop, totalCount) {
      const start = Math.floor(scrollTop / itemHeight);
      const end = Math.min(start + this.visibleCount, totalCount);
      return { start, end };
    },
    
    getOffsetY(index) {
      return index * itemHeight;
    }
  };
}

// 图片懒加载
export function createImageLazyLoader() {
  const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        const img = entry.target;
        img.src = img.dataset.src;
        img.classList.remove('lazy');
        observer.unobserve(img);
      }
    });
  });
  
  return {
    observe(img) {
      observer.observe(img);
    },
    unobserve(img) {
      observer.unobserve(img);
    }
  };
}

// 批量DOM更新优化
export function batchUpdate(updates) {
  return new Promise(resolve => {
    requestAnimationFrame(() => {
      updates.forEach(update => update());
      resolve();
    });
  });
}

// 数据分片处理
export function chunkArray(array, chunkSize = 1000) {
  const chunks = [];
  for (let i = 0; i < array.length; i += chunkSize) {
    chunks.push(array.slice(i, i + chunkSize));
  }
  return chunks;
}

// 异步处理大数据
export async function processLargeData(data, processor, chunkSize = 1000) {
  const chunks = chunkArray(data, chunkSize);
  const results = [];
  
  for (const chunk of chunks) {
    const chunkResult = await new Promise(resolve => {
      setTimeout(() => {
        resolve(processor(chunk));
      }, 0);
    });
    results.push(...chunkResult);
  }
  
  return results;
}

// 深度克隆优化
export function deepClone(obj, hash = new WeakMap()) {
  if (obj === null || typeof obj !== 'object') return obj;
  if (obj instanceof Date) return new Date(obj);
  if (obj instanceof RegExp) return new RegExp(obj);
  
  if (hash.has(obj)) return hash.get(obj);
  
  const cloneObj = Array.isArray(obj) ? [] : {};
  hash.set(obj, cloneObj);
  
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      cloneObj[key] = deepClone(obj[key], hash);
    }
  }
  
  return cloneObj;
}

// 防抖搜索
export function createSearchDebouncer(callback, delay = 300) {
  let timeoutId;
  
  return function(searchTerm) {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => {
      callback(searchTerm);
    }, delay);
  };
}

// 性能监控
export function createPerformanceMonitor() {
  const metrics = {
    startTime: Date.now(),
    operations: [],
    
    start(label) {
      return {
        label,
        startTime:  Date.now()
      };
    },
    
    end(operation) {
      const duration = Date.now() - operation.startTime;
      this.operations.push({
        label: operation.label,
        duration
      });
      
      if (duration > 100) {
        console.warn(`Performance warning: ${operation.label} took ${duration.toFixed(2)}ms`);
      }
    },
    
    getMetrics() {
      return {
        totalTime: Date.now() - this.startTime,
        operations: this.operations,
        averageTime: this.operations.reduce((sum, op) => sum + op.duration, 0) / this.operations.length
      };
    }
  };
  
  return metrics;
} 